package com.ikun.core.plugin.storage;

import com.ikun.core.config.GlobalConfig;
import com.ikun.core.enums.FileTypeEnum;
import com.ikun.core.exception.InternalOperationException;
import com.ikun.core.plugin.storage.engine.LocalStorage;
import com.ikun.core.pojo.vo.UploadFilesVo;
import com.ikun.core.utils.RequestContextUtils;
import com.ikun.core.utils.TimeUtils;
import org.springframework.web.multipart.MultipartFile;

import java.util.Arrays;
import java.util.Objects;
import java.util.UUID;

/**
 * 存储引擎
 */
enum EngineType {
    LOCAL, QINIU, ALIYUN, QCLOUD
}

/**
 * 存储驱动
 */
public class StorageDriver {

    /**
     * 当前存储引擎
     */
    private final EngineType engine;


    public StorageDriver() {
        this.engine = EngineType.LOCAL;
    }

    /**
     * 根据引擎类型上传文件
     *
     * @param multipartFile 文件对象
     * @param type          文件类型
     * @return UploadFilesVo
     */
    public UploadFilesVo upload(MultipartFile multipartFile, FileTypeEnum type) {
        this.checkFile(multipartFile, type);

        String savedName = this.buildSaveName(multipartFile);
        String fileType = type.getMsg();
        String date = TimeUtils.timestampToDate(TimeUtils.timestamp(), "yyyyMMdd");

        switch (this.engine) {
            case LOCAL:
                LocalStorage local = new LocalStorage();
                local.saveToStorage(multipartFile, fileType, date, savedName);
                break;
            case QINIU:
                break;
            case ALIYUN:
                break;
            case QCLOUD:
                break;
        }

        String host = RequestContextUtils.uri();
        String path = "/" + GlobalConfig.publicPrefix + "/" + fileType + "/" + date + "/" + savedName;

        UploadFilesVo vo = new UploadFilesVo();
        vo.setName(multipartFile.getOriginalFilename());
        vo.setSize(multipartFile.getSize());
        vo.setExt(this.getFileExt(multipartFile));
        vo.setUrl(host + GlobalConfig.contextPath + path); // http://localhost:8112/api/fetch/file/image/20250809/a95f788b-6372-413e-88f0-b41556df2c2d.jpg
        vo.setPath(path); // /fetch/file/image/20250809/a95f788b-6372-413e-88f0-b41556df2c2d.jpg

        return vo;
    }


    /**
     * 生成文件名称
     *
     * @param multipartFile 文件对象
     * @return String a95f788b-6372-413e-88f0-b41556df2c2d.jpg
     */
    private String buildSaveName(MultipartFile multipartFile) {
        return UUID.randomUUID() + this.getFileExt(multipartFile);
    }

    /**
     * 获取文件后缀
     *
     * @param multipartFile 文件对象
     * @return String 小写文件后缀 .jpg
     */
    private String getFileExt(MultipartFile multipartFile) {
        String name = multipartFile.getOriginalFilename();
        return Objects.requireNonNull(name).substring(name.lastIndexOf(".")).toLowerCase();
    }

    /**
     * 文件验证
     *
     * @param multipartFile 文件对象
     * @param type          文件类型
     */
    private void checkFile(MultipartFile multipartFile, FileTypeEnum type) {
        String fileExt = this.getFileExt(multipartFile).substring(1);
        long fileSize = multipartFile.getSize();

        switch (type) {
            case IMAGE:
                if (!Arrays.asList(GlobalConfig.uploadImageExt).contains(fileExt)) {
                    throw new InternalOperationException("不被支持的扩展:" + fileExt);
                }
                if (fileSize > GlobalConfig.uploadImageSize) {
                    throw new InternalOperationException("上传图片不能超出限制:" + (GlobalConfig.uploadImageSize / 1024 / 1024) + "M");
                }
                break;
            case VIDEO:
                if (!Arrays.asList(GlobalConfig.uploadVideoExt).contains(fileExt)) {
                    throw new InternalOperationException("不被支持的扩展:" + fileExt);
                }
                break;
            case AUDIO:
                if (!Arrays.asList(GlobalConfig.uploadAudioExt).contains(fileExt)) {
                    throw new InternalOperationException("不被支持的扩展:" + fileExt);
                }
                break;
            case DOC:
                if (!Arrays.asList(GlobalConfig.uploadDocExt).contains(fileExt)) {
                    throw new InternalOperationException("不被支持的扩展:" + fileExt);
                }
                break;
            case OTHER:
                break;
        }

    }
}
